﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Resources;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using AjaxControlFramework.Reflection;

namespace AjaxControlFramework
{
	public abstract class AuthenticationStrategy : IAjaxControlStrategy
	{
		//------// Properties \\--------------------------------------------\\
		public virtual IAjaxControl Control { get; set; }
        public virtual Control TargetControl { get; set; }


        private Type _targetControlType = null;
        public virtual Type TargetControlType
        {
            get
            {
                if (_targetControlType == null)
                {
                    _targetControlType = TargetControl.GetType();
                }

                return _targetControlType;
            }
            set
            {
                _targetControlType = value;
            }
        }


        private Type _baseTargetControlType = null;
        public virtual Type BaseTargetControlType
        {
            get
            {
                if (_baseTargetControlType == null)
                {
                    if (TargetControlType != null)
                    {
                        _baseTargetControlType = AjaxControlUtils.ResolveBaseControlType(TargetControlType);
                    }
                    else
                    {
                        _baseTargetControlType = TargetControlType;
                    }
                }

                return _baseTargetControlType;
            }
        }


        private Page _parentPage = null;
        public virtual Page ParentPage
        {
            get
            {
                if (_parentPage == null)
                {
                    if (Control == null) { return null; }

                    if ((Control as Control).Page == null)
                    {
                        _parentPage = (HttpContext.Current.CurrentHandler as Page);

                        if (_parentPage == null)
                        {
                            _parentPage = (Page)HttpContext.Current.Items["AjaxControlFramework.AjaxControlHandler.CurrentPage"];
                        }
                    }
                    else
                    {
                        _parentPage = (Control as Control).Page;
                    }
                }

                return _parentPage;
            }
        }


        public abstract bool Authenticated { get; }
        //------\\ Properties //--------------------------------------------//



        //------// Constructors \\------------------------------------------\\
		protected AuthenticationStrategy(Control control)
		{
			if (control == null) { throw new ArgumentNullException("control"); }
			if (!(control is IAjaxControl)) { throw new ArgumentException("A reference of type IAjaxControl was expected.", "control"); }

			Control = (IAjaxControl)control;
		}
		//------\\ Constructors //------------------------------------------//



		//------// Methods \\-----------------------------------------------\\
        
		//------\\ Methods //-----------------------------------------------//



		//------// Abstract Methods \\--------------------------------------\\
        protected abstract string[] GetRolesOfAuthenticatedUser();


        public virtual bool UserIsAuthorized(string[] authorizedRoles)
        {
            if (authorizedRoles == null || authorizedRoles.Length == 0) { return true; }


            string[] userRoles = GetRolesOfAuthenticatedUser();

            foreach (string userRole in userRoles)
            {
                if (authorizedRoles.Contains(userRole))
                {
                    return true;
                }
            }


            return false;
        }


        protected virtual void ValidateUserRoles(string[] userRoles)
        {
            if (userRoles == null) { return; }

            foreach (string userRole in userRoles)
            {
                if (String.IsNullOrWhiteSpace(userRole))
                {
                    throw new InvalidUserRolesException("The array of user roles contains one or more null/empty string values.");
                }
            }
        }
		//------\\ Abstract Methods //--------------------------------------//
	}
}
